#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <string.h>

struct msgbuf {
        long mtype;       /* message type, must be > 0 */
        char mtext;    /* message data */
};

union semun {
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
           };

void Init_sem(int semid,int value){

	union semun tmp;
	tmp.val = value;
	if((semctl(semid,0,SETVAL,tmp)) == -1){
		
		perror("Init sem error");
		exit(-1);		
	}
}

int Del_sem(int semid){
	
	union semun tmp;
	if((semctl(semid,0,IPC_RMID,tmp)) == -1){
	
		perror("Del sem error");
		exit(-1);		
	}
}

void v_sem(int semid){

	struct sembuf sbuf;

	sbuf.sem_num = 0;        /* Operate on semaphore 0 */
        sbuf.sem_op = 1;         /* Wait for value to equal 0 */
        sbuf.sem_flg = SEM_UNDO;
	if(semop(semid,&sbuf,1) == -1){
		
		perror("V error why");
		exit(-1);
	}
}


void p_sem(int semid){

	struct sembuf sbuf;

	sbuf.sem_num = 0;        /* Operate on semaphore 0 */
        sbuf.sem_op = -1;         /* Wait for value to equal 0 */
        sbuf.sem_flg = SEM_UNDO;
	if(semop(semid,&sbuf,1) == -1){
		
		perror("P error why");
		exit(-1);
	}
}

void clear_input_buffer(){
	
	int c;
	while ((c = getchar()) != '\n' && c != EOF);
}

int main(){

	key_t key;
	int semid;
	int shmid;
	int msqid;
	char *shmddr;
	struct msgbuf msg;
	int flag = 1;

	if((key = ftok(".",'m')) < 0){
		
		perror("ftok error");
		exit(-1);
	}

	if((semid = semget(key,1,0)) == -1){
		
		perror("segmet error");
		exit(-1);
	}

	if((msqid = msgget(key,IPC_CREAT|0777)) == -1){

                perror("msgget error");
                exit(-1);
        }

	 if((shmid = shmget(key, 1024, 0)) == -1){
	
	 	perror("Create Shared Memory Error");
		exit(-1);
	}

	shmddr = (char*)shmat(shmid, 0, 0);
	if(shmddr == (void*)-1){
		
		perror("Attach Shared Memory Error");
		exit(-1);
	}

	printf("***************************************\n");  
	printf("*                 IPC                 *\n");  
	printf("*    Input r to send data to server.  *\n");  
	printf("*    Input q to quit.                 *\n");  
	printf("***************************************\n");

	while(flag){
		
		char c;
		printf("Input cmd :");
		scanf(" %c",&c);
		clear_input_buffer();
		
		switch(c){
		
			case 'r':
				printf("Data to send:");
				p_sem(semid);
				//scanf("%s",shmddr);
				fgets(shmddr, 1024, stdin);
				shmddr[strcspn(shmddr, "\n")] = '\0';
				v_sem(semid);

				//while((c=getchar())!='\n' && c!=EOF);
				msg.mtype = 888;
				msg.mtext = 'r';
				msgsnd(msqid,&msg,sizeof(msg.mtext),0);
				break;
			case 'q':
				msg.mtype = 888;
				msg.mtext = 'q';
				msgsnd(msqid,&msg,sizeof(msg.mtext),0);
				flag = 0;
				break;
			default:
				printf("input error\n");
		}
	}

	shmdt(shmddr);

	return 0;
}

